package brand

import (
	"context"
	"net/http"

	"github.com/gin-gonic/gin"

	"mxshop-api/goods-web/api"
	"mxshop-api/goods-web/forms/brand"
	"mxshop-api/goods-web/global"
	proto "mxshop-api/goods-web/proto/gen/v1"
)

func List(c *gin.Context) {
	var pagination brand.Pagination
	err := c.ShouldBind(&pagination)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}
	if pagination.PageSize == 0 {
		pagination.PageSize = 10
	}

	resp, err := proto.NewGoodsClient(global.Conn).BrandList(context.Background(), &proto.BrandFilterRequest{
		Pages:       pagination.Page,
		PagePerNums: pagination.PageSize,
	})

	data := make([]gin.H, 0, len(resp.Data))
	for _, value := range resp.Data {
		data = append(data, InfoGrpcToMap(value))
	}

	c.JSON(http.StatusOK, gin.H{
		"total": resp.Total,
		"data":  data,
	})
}

func Create(c *gin.Context) {
	var form brand.Form
	err := c.ShouldBind(&form)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	resp, err := proto.NewGoodsClient(global.Conn).CreateBrand(context.Background(), &proto.BrandRequest{
		Name: form.Name,
		Logo: form.Logo,
	})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"id":   resp.Id,
		"name": form.Name,
		"logo": form.Logo,
	})
}

func Update(c *gin.Context) {
	var brandIns brand.Brand
	err := c.ShouldBindUri(&brandIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	var form brand.Form
	err = c.ShouldBind(&form)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	_, err = proto.NewGoodsClient(global.Conn).UpdateBrand(context.Background(), &proto.BrandRequest{
		Id:   brandIns.ID,
		Name: form.Name,
		Logo: form.Logo,
	})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.Status(http.StatusCreated)
}

func Delete(c *gin.Context) {
	var brandIns brand.Brand
	err := c.ShouldBindUri(&brandIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	_, err = proto.NewGoodsClient(global.Conn).DeleteBrand(context.Background(),
		&proto.BrandRequest{Id: brandIns.ID})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.Status(http.StatusNoContent)
}

// CategoryBrandList 获取类别品牌列表页
func CategoryBrandList(c *gin.Context) {
	var pagination brand.Pagination
	err := c.ShouldBind(&pagination)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	resp, err := proto.NewGoodsClient(global.Conn).CategoryBrandList(context.Background(),
		&proto.CategoryBrandFilterRequest{
			Pages:       pagination.Page,
			PagePerNums: pagination.PageSize,
		})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	data := make([]gin.H, 0, len(resp.Data))
	for _, value := range resp.Data {
		data = append(data, CategoryBrandBufToMap(value))
	}

	c.JSON(http.StatusOK, gin.H{
		"total": resp.Total,
		"data":  data,
	})
}

// GetCategoryBrandList 获取分类的品牌(通过category获取brands)
func GetCategoryBrandList(c *gin.Context) {
	var categoryIns brand.Category
	err := c.ShouldBindUri(&categoryIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	resp, err := proto.NewGoodsClient(global.Conn).GetCategoryBrandList(context.Background(),
		&proto.CategoryInfoRequest{
			Id: categoryIns.ID,
		})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	data := make([]interface{}, 0, len(resp.Data))
	for _, value := range resp.Data {
		data = append(data, InfoGrpcToMap(value))
	}

	c.JSON(http.StatusOK, gin.H{
		"total": resp.Total,
		"data":  data,
	})
}

func NewCategoryBrand(c *gin.Context) {
	var categoryBrandForm brand.CategoryBrandForm
	err := c.ShouldBind(&categoryBrandForm)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	resp, err := proto.NewGoodsClient(global.Conn).CreateCategoryBrand(context.Background(),
		&proto.CategoryBrandRequest{
			CategoryId: categoryBrandForm.CategoryId,
			BrandId:    categoryBrandForm.BrandId,
		})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.JSON(http.StatusCreated, gin.H{"id": resp.Id})
}

func UpdateCategoryBrand(c *gin.Context) {
	var categoryBrandIns brand.CategoryBrand
	err := c.ShouldBindUri(&categoryBrandIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	var categoryBrandForm brand.CategoryBrandForm
	err = c.ShouldBind(&categoryBrandForm)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	_, err = proto.NewGoodsClient(global.Conn).UpdateCategoryBrand(context.Background(), &proto.CategoryBrandRequest{
		Id:         categoryBrandIns.ID,
		CategoryId: categoryBrandForm.CategoryId,
		BrandId:    categoryBrandForm.BrandId,
	})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.Status(http.StatusCreated)
}

func DeleteCategoryBrand(c *gin.Context) {
	var categoryBrandIns brand.CategoryBrand
	err := c.ShouldBindUri(&categoryBrandIns)
	if err != nil {
		api.HandleValidatorError(c, err)
		return
	}

	_, err = proto.NewGoodsClient(global.Conn).DeleteCategoryBrand(context.Background(), &proto.CategoryBrandRequest{
		Id: categoryBrandIns.ID,
	})
	if err != nil {
		api.HandleGrpcErrorToHttp(c, err)
		return
	}

	c.Status(http.StatusNoContent)
}

func InfoGrpcToMap(info *proto.BrandInfoResponse) gin.H {
	return gin.H{
		"id":   info.Id,
		"name": info.Name,
		"logo": info.Logo,
	}
}

func CategoryBrandBufToMap(info *proto.CategoryBrandResponse) gin.H {
	return gin.H{
		"id":    info.Id,
		"brand": InfoGrpcToMap(info.Brand),
		"category": gin.H{
			"id":   info.Category.Id,
			"name": info.Category.Name,
		},
	}
}
